package handler

import (
	"fmt"
	"strings"
	"net/http"
	"encoding/base64"

	"github.com/gorilla/mux"

	"read.com/wxmp/dao"
	"read.com/wxmp/crypto"
	"read.com/wxmp/service"
)

func registerWechatHandler(r *mux.Router) {
	r.Methods(http.MethodGet, http.MethodPost).Path("/{app:[A-Za-z]+}").HandlerFunc(wechatHandler)
}

func wechatHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	app := dao.GetAppByName(vars["app"])
	if app == nil {
		fmt.Println("app not found.", vars["app"])
		return
	}

	// 第一次签名校验
	nonce := r.FormValue("nonce")
	timestamp := r.FormValue("timestamp")
	signature := r.FormValue("signature")
	if sign := crypto.BuildSign([]string{timestamp, nonce, app.DevToken}); sign != signature {
		fmt.Println("signature not match.", sign, signature, vars["app"])
		w.Write([]byte("sign not match"))
		return
	}

	if echo := r.FormValue("echostr"); echo != "" {
		w.Write([]byte(echo))
		return
	}

	// 安全模式下再次校验签名
	reply := false
	if r.Method == "POST" && r.FormValue("encrypt_type") == "aes" {
		encryptRequestBody := crypto.ParseEncryptRequestBody(r)
		if ok := crypto.CheckSignatureAgain(r, encryptRequestBody, app.DevToken); !ok {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
		// 解密xml消息 Decode base64
		cipherData, err := base64.StdEncoding.DecodeString(encryptRequestBody.Encrypt)
		if err != nil {
			fmt.Println("Decode base64 error:", err)
		}
		//  解密xml消息 用aesKey解密解码后的cipherData
		plainData, err := crypto.AesDecrypt(cipherData, []byte(crypto.AesKey(app.DevMsgKey)))
		if err != nil {
			fmt.Println("Decrypt error:", err)
		}
		// 解密后的plainData做appID校验以及xml Decoding处理
		if xmlMap, err := crypto.ParseEncryptTextRequestBody(plainData, app.DevId); err != nil {
			fmt.Println("xml解析失败:", err)
		} else if len(xmlMap) > 0 {
			reply = handleWechatNotify(w, xmlMap, app, nonce, timestamp)
		}
	}
	if reply {
		return
	}
	w.Write([]byte("success"))
}

// 处理消息和事件推送
func handleWechatNotify(w http.ResponseWriter, data map[string]string, app *dao.SysApp, nonce, timestamp string) bool {
	msgType := strings.ToLower(data["MsgType"])
	event := strings.ToLower(data["Event"])
	eventKey := strings.ToLower(data["EventKey"])

	wechatService := service.NewWechatService(dao.GetSession(), app, data["FromUserName"])
	defer wechatService.Close()
	wechatService.InitUser()

	switch {
	case msgType == "event" && event == "subscribe": // 用户关注
		wechatService.Subscribe(eventKey != "")
	case msgType == "event" && event == "unsubscribe": // 用户取消关注
		wechatService.UnSubscribe()
	case msgType == "text": // 触发被动回复消息
		return wechatService.ReplyMsg(w, data["Content"], nonce, timestamp)
		//case msgType == "image":
		//	fmt.Println("image")
		//case msgType == "voice":
		//	fmt.Println("voice")
		//case msgType == "video":
		//	fmt.Println("video")
		//case msgType == "shortvideo":
		//	fmt.Println("shortvideo")
		//case msgType == "location":
		//	fmt.Println("location")
		//case msgType == "link":
		//	fmt.Println("link")
		//case event == "CLICK" && eventKey == "SIGN": // 触发客服消息
		//	service.SignText(accessToken, openid)
		//case event == "CLICK" && eventKey == "HOTLIST": // 触发客服消息
		//	service.GetHot(accessToken, openId)
	}
	return false
}
